#include "UdpSocketWrapper.hpp"
#include <sys/socket.h>
#include <unordered_map>
#include "UdpSocket.hpp"
#include "common/HiCommonLog.hpp"

using namespace std;

const char*  UdpSocketWrapper::GetErrorScript(int error) {
	if (-1 == error) {
		return "maybe this is a user defined error,eg:ip is not v4";
	}
	return  uv_strerror(error);
}

UdpSocketWrapper::UdpSocketWrapper() {	
}

UdpSocketWrapper::~UdpSocketWrapper() {
	if (nullptr == this->impl) {
		return;
	}
	
	delete this->impl;
	this->impl = nullptr;
}

int UdpSocketWrapper::Listen(const char* ip, uint16_t port, const CALL_BACK& onReceive) {
	if (this->impl != nullptr) {
		return -1;
	}
	this->impl = new UdpSocket();
	int ret = this->impl->Listen(ip, port, [&](const uint8_t* data, size_t len, const struct sockaddr* addr){
		HI_DEBUG("UdpSocketWrapper onReceive is called\n");
		HI_DEBUG("UdpSocketWrapper onReceive begin\n");
		onReceive(data, len, addr, this);
		HI_DEBUG("UdpSocketWrapper onReceive end\n");
	}, [&](){
		if (this->impl != nullptr) {
			this->impl = nullptr;
		}
	}, [&](int reason){		
	});
	HI_DEBUG("UdpSocketWrapper::Listen\n");
	return ret;
}

int UdpSocketWrapper::Listen(const char* ip, uint16_t port) {
	if (this->impl != nullptr) {
		return -1;
	}
	this->impl = new UdpSocket();
	int ret = this->impl->Listen(ip, port, [&](const uint8_t* data, size_t len, const struct sockaddr* addr){
		HI_DEBUG("UdpSocketWrapper onReceive is called, not set handle function, maybe this only use to senf\n");
	}, [&](){
		if (this->impl != nullptr) {
			this->impl = nullptr;
		}
	}, [&](int reason){		
	});
	HI_DEBUG("UdpSocketWrapper::Listen\n");
	return ret;
}

void UdpSocketWrapper::Destroy() {
	if (nullptr == this->impl) {
		return;
	}
	HI_DEBUG("UdpSocketWrapper::Destroy\n");
	this->impl->Destroy();
}
void UdpSocketWrapper::Send(const uint8_t *data, size_t len, const struct sockaddr *addr) {
	if (nullptr == this->impl) {
		return;
	}
	HI_DEBUG("UdpSocketWrapper::Send\n");
	this->impl->Send(data, len, addr);
}
void UdpSocketWrapper::Send(const uint8_t *data, size_t len, const char* ip,  uint16_t port) {
	if (nullptr == this->impl) {
		return;
	}
	HI_DEBUG("UdpSocketWrapper::Send\n");
	this->impl->Send(data, len, ip, port);
}

const struct sockaddr *UdpSocketWrapper::GetLocalAddress() const {
	if (nullptr == this->impl) {
		return nullptr;
	}
	return this->impl->GetLocalAddress();
}

string UdpSocketWrapper::GetLocalIP() {
	if (nullptr == this->impl) {
		return "";
	}
	return this->impl->GetLocalIP();
}
uint16_t UdpSocketWrapper::GetLocalPort() const {
	if (nullptr == this->impl) {
		return 0;
	}
	return this->impl->GetLocalPort();
}
size_t UdpSocketWrapper::GetRecvBytes() const {
	if (nullptr == this->impl) {
		return 0;
	}
	return this->impl->GetRecvBytes();
}
size_t UdpSocketWrapper::GetSentBytes() const {
	if (nullptr == this->impl) {
		return 0;
	}
	return this->impl->GetSentBytes();
}